/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 * Description: define cast source discovery.
 * Create: 2024-03-22
 */

#ifndef WIFI_DISPLAY_MANAGER_H
#define WIFI_DISPLAY_MANAGER_H

#include <mutex>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>

#include "cast_engine_common.h"
#include "cast_service_common.h"
#include "wfd_source.h"
#include "wfd_sink.h"
#include "connection_hap_ability.h"

namespace OHOS {
namespace CastEngine {
namespace CastEngineService {
class IWifiDisplayDeviceListener {
public:
    IWifiDisplayDeviceListener() = default;
    IWifiDisplayDeviceListener(const IWifiDisplayDeviceListener &) = delete;
    IWifiDisplayDeviceListener &operator=(const IWifiDisplayDeviceListener &) = delete;
    IWifiDisplayDeviceListener(IWifiDisplayDeviceListener &&) = delete;
    IWifiDisplayDeviceListener &operator=(IWifiDisplayDeviceListener &&) = delete;
    virtual ~IWifiDisplayDeviceListener() = default;
    virtual void OnDeviceFound(const std::vector<CastInnerRemoteDevice> &devices) = 0;
    virtual void OnDeviceOffline(const std::string &deviceId) = 0;
};

class IWifiDisplayStateListener {
public:
    IWifiDisplayStateListener() = default;
    IWifiDisplayStateListener(const IWifiDisplayStateListener &) = delete;
    IWifiDisplayStateListener &operator=(const IWifiDisplayStateListener &) = delete;
    IWifiDisplayStateListener(IWifiDisplayStateListener &&) = delete;
    IWifiDisplayStateListener &operator=(IWifiDisplayStateListener &&) = delete;
    virtual ~IWifiDisplayStateListener() = default;
    virtual void OnConnectionChanged(DeviceState state, const std::string &deviceId, const std::string &deviceName) = 0;
    virtual void OnConnectionError(DeviceState state, const std::string &deviceId, int32_t errCode) = 0;
};

class WifiDisplayManager {
public:
    static WifiDisplayManager &GetInstance();

    void Init(std::shared_ptr<IWifiDisplayDeviceListener> listener);
    void DeInit();

    void StartDiscovery();
    void StopDiscovery();

    void AddCastDevice(const std::string deviceId);
    void RemoveCastDevice(const std::string deviceId);

    void SetParamter(const std::string &param);
    void RegisterStateListener(const std::shared_ptr<IWifiDisplayStateListener>& listener);
    void UnregisterStateListener();
    void OnInfo(std::shared_ptr<Sharing::BaseMsg> &msg);

    void SetAudioOutput(EndType type);
    bool SetSinkDiscoverable(bool isDiscoverable);
    bool RegisterSinkEventListener(const std::shared_ptr<Sharing::IWfdEventListener> &listener);
    bool AcceptDeviceConnection(const std::string &deviceId, bool accept);
    bool Play(const std::string &deviceId);
    bool Pause(const std::string &deviceId);
    bool SetSurface(const std::string &deviceId, sptr<IBufferProducer> producer);
    bool RemoveSurface(const std::string &deviceId, uint64_t surfaceId);
    bool Close(const std::string &deviceId);

private:
    enum WifiDisplayState {
        STATE_NONE,
        STATE_DISCOVERY,
        STATE_CONNECTING,
        STATE_CONNECTED,
        STATE_DISCONNECTING,
        STATE_DISCONNECTED,
        STATE_MAX
    };

    WifiDisplayManager() = default;
    ~WifiDisplayManager() = default;
    WifiDisplayManager(const WifiDisplayManager &)= delete;
    WifiDisplayManager &operator=(const WifiDisplayManager &) = delete;
    WifiDisplayManager(WifiDisplayManager &&) = delete;
    WifiDisplayManager &operator=(WifiDisplayManager &&) = delete;

    bool RestartSource();
    void OnDied();
    void OnError(std::shared_ptr<Sharing::WfdErrorMsg> &msg);
    static int32_t GetErrorCode(int32_t errorCode);

    void SetListener(const std::shared_ptr<IWifiDisplayDeviceListener>& listener);
    bool HasListener();
    void ResetListener();

    void OnDeviceOffline();
    void OnDeviceOffline(const std::string &deviceId);
    void OnConnectionChanged(const Sharing::ConnectionInfo &info);
    void OnDeviceFound(const std::vector<Sharing::WfdCastDeviceInfo> &deviceInfos);
    void SetWifiDisplayState(bool connect);

    std::shared_ptr<Sharing::WfdSink>& GetWfdSink();

    std::mutex mutex_;
    std::shared_ptr<IWifiDisplayDeviceListener> deviceListener_;
    std::shared_ptr<IWifiDisplayStateListener> stateListener_;
    std::shared_ptr<Sharing::IWfdEventListener> wfdListener_;
    std::map<std::string, CastInnerRemoteDevice> devices_;
    std::shared_ptr<Sharing::WfdSource> sourceclient_ = nullptr;
    std::shared_ptr<Sharing::WfdSink> sinkClient_ = nullptr;
    static std::unordered_map<int32_t, int32_t> ErrorMapping_;

    std::mutex stateMutex_;
    std::mutex deviceMutex_;
    bool isConnected_ = false;
    bool isEnablePowerForce_ = false;
    Sharing::ConnectionInfo currConnectionInfo;
    sptr<CastAbilityConnection> connection_ = nullptr;
};
} // namespace CastEngineService
} // namespace CastEngine
} // namespace OHOS
#endif // DLNA_MANAGER_H
